package com.wwdeng.print.app.printer;


import android.annotation.SuppressLint;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Locale;

/**
 * PrintTestDemo
 * @Author：wwdeng
 * @CreateTime：2025/4/1 00:35
 * <pre>
 * 指令工具类
 * </pre>
 */
public class EscPosUtils {

    // 初始化打印机
    public static byte[] initPrinter() {
        return new byte[]{27, 64};
    }

    // 换行
    public static byte[] lineFeed() {
        return new byte[]{10};
    }

    // 换多行
    public static byte[] lineFeeds(int n) {
        return new byte[]{27, 100, (byte) n};
    }

    // 设置对齐方式 0:左对齐 1:居中 2:右对齐
    public static byte[] setAlign(int align) {
        return new byte[]{27, 97, (byte) align};
    }

    /**
     *
     * 17 -> 2倍宽高
     * 51 -> 4倍宽高
     */
    // 设置字体大小 0:正常大小 1:双倍高度 2:双倍宽度 3:双倍大小
    public static byte[] setFontSize(int size) {
        return new byte[]{29, 33, (byte) size};
    }

    // 设置加粗
    public static byte[] setBold(boolean bold) {
        return new byte[]{27, 69, (byte) (bold ? 1 : 0)};
    }

    // 设置下划线
    public static byte[] setUnderline(boolean underline) {
        return new byte[]{27, 45, (byte) (underline ? 1 : 0)};
    }

    // 设置行间距
    public static byte[] setLineSpacing(int spacing) {
        return new byte[]{27, 51, (byte) spacing};
    }

    //设置条码数字位置 0:不显示 1:上方 2:下方 3:上下都显示
    public static byte[] selectHRICharacterPrintPosition(int n) {
        return new byte[]{29, 72, (byte)n};
    }

    //设置条码宽度
    public static byte[] setBarcodeWidth(int n) {
        return new byte[]{29, 119, (byte)n};
    }

    //设置条码高度
    public static byte[] setBarcodeHeight(int n) {
        return new byte[]{29, 104, (byte)n};
    }

    // 打印文本
    public static byte[] printText(String text) {
        try {
            return text.getBytes("GBK");
        } catch (Exception e) {
            return text.getBytes();
        }
    }

    // 打印文本
    public static byte[] printText(String text,String charset) {
        try {
            return text.getBytes(charset);
        } catch (Exception e) {
            return text.getBytes();
        }
    }

    // 打印并换行
    public static byte[] printLine(String text) {
        return concatBytes(printText(text), lineFeed());
    }

    // 切纸
    public static byte[] cutPaper() {
        return new byte[]{29, 86, 66, 0};
    }

    // 部分切纸
    public static byte[] partialCutPaper() {
        return new byte[]{29, 86, 65, 0};
    }

    // 打开钱箱
    public static byte[] openCashDrawer() {
        return new byte[]{27, 112, 0, 60, 120};
    }

    // 打印一维条码
    public static byte[] printBarcode(String data, int barcodeType, int height, int width, int position) {
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        try {
            // 设置条码高度
            buffer.write(setBarcodeHeight(height));
            // 设置条码宽度
            buffer.write(setBarcodeWidth(width));
            // 设置条码数字位置 0:不显示 1:上方 2:下方 3:上下都显示
            buffer.write(selectHRICharacterPrintPosition(position));
            // 打印条码
            buffer.write(new byte[]{29, 107, (byte) barcodeType});
            buffer.write(data.getBytes());
            buffer.write(0);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return buffer.toByteArray();
    }

    // 打印二维码
    public static byte[] printQRCode(String data, int size, int errorCorrection) {
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        try {
            // 设置二维码大小 1-16
            buffer.write(new byte[]{29, 40, 107, 3, 0, 49, 67, (byte) size});
            // 设置纠错等级 48-51 (L-7%, M-15%, Q-25%, H-30%)
            buffer.write(new byte[]{29, 40, 107, 3, 0, 49, 69, (byte) errorCorrection});
            // 存储数据
            buffer.write(new byte[]{29, 40, 107, (byte) (data.length() + 3), 0, 49, 80, 48});
            buffer.write(data.getBytes("GBK"));
            // 打印二维码
            buffer.write(new byte[]{29, 40, 107, 3, 0, 49, 81, 48});
        } catch (IOException e) {
            e.printStackTrace();
        }
        return buffer.toByteArray();
    }

    // 打印图片(需要将图片转换为黑白点阵数据)
    public static byte[] printImage(byte[] imageData, int width) {
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        try {
            // 设置位图模式
            buffer.write(new byte[]{29, 118, 48, 0});
            // 宽度低字节
            buffer.write((byte) (width % 256));
            // 宽度高字节
            buffer.write((byte) (width / 256));
            buffer.write(imageData);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return buffer.toByteArray();
    }

    // 合并多个byte数组
    public static byte[] concatBytes(byte[]... bytes) {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        try {
            for (byte[] b : bytes) {
                outputStream.write(b);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return outputStream.toByteArray();
    }

    // 打印分隔线
    public static byte[] printDivider(char lineChar, int length) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            sb.append(lineChar);
        }
        return printLine(sb.toString());
    }

    /**
     *
     * 打印两列文本(左列和右列)
     * @param leftText: 左侧文字
     * @param rightText： 右侧文字
     * @param lineLength： 行宽 （80mm -> 48）
     * @return
     */
    public static byte[] printTwoColumns(String leftText, String rightText, int lineLength) {
        int leftLength = getGbkLength(leftText);
        int rightLength = getGbkLength(rightText);

        if (leftLength + rightLength > lineLength) {
            // 如果两列文本太长，分行打印
            return concatBytes(printLine(leftText), printLine(rightText));
        } else {
            // 计算中间空格数
            int spaces = lineLength - leftLength - rightLength;
            StringBuilder sb = new StringBuilder();
            sb.append(leftText);
            for (int i = 0; i < spaces; i++) {
                sb.append(" ");
            }
            sb.append(rightText);
            return printLine(sb.toString());
        }
    }

    /**
     * 生成高级格式打印数据
     * @param leftItems 左列内容列表
     * @param rightItems 右列内容列表
     * @return ESC/POS指令字节数组
     * @throws IOException 如果发生I/O错误
     */
    public static byte[] generateDoubleSizeColumns(List<String> leftItems, List<String> rightItems) throws IOException {
        if (leftItems == null || rightItems == null || leftItems.size() != rightItems.size()) {
            throw new IllegalArgumentException("左右列数据不能为空且长度必须一致");
        }

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        // 1. 设置双倍宽高并加粗
        setDoubleSizeBold(outputStream, true);

        // 2. 打印数据行
        for (int i = 0; i < leftItems.size(); i++) {
            printDataRow(outputStream, leftItems.get(i), rightItems.get(i));
        }

        // 3. 恢复默认字体样式
        setDoubleSizeBold(outputStream, false);

        return outputStream.toByteArray();
    }

    /**
     * 设置双倍大小加粗字体
     * @param enable true:启用 false:禁用
     */
    private static void setDoubleSizeBold(ByteArrayOutputStream stream, boolean enable) throws IOException {
        if (enable) {
            //双倍宽高行间距需要加高
            stream.write(setLineSpacing(120));
            // 双倍宽高 (GS ! 0x30) + 加粗 (ESC E 1)
            stream.write(setFontSize(17));// 双倍宽高
            stream.write(setBold(true));// 加粗
        } else {
            //恢复80行间距
            stream.write(setLineSpacing(80));
            // 恢复正常 (GS ! 0x00) + 取消加粗 (ESC E 0)
            stream.write(setFontSize(0));// 正常大小
            stream.write(setBold(false));// 取消加粗
        }
    }

    /**
     * 打印数据行
     */
    private static void printDataRow(ByteArrayOutputStream stream, String leftText, String rightText) throws IOException {
        // 左列内容（靠左）
        stream.write(setAlign(0)); // 左对齐
        stream.write(printText(leftText));

        // 右列内容（靠右+反白）
        stream.write(setAlign(2)); // 右对齐
        stream.write(setReverseMode(true));// 反白显示
        stream.write(printText(rightText));
        stream.write(setReverseMode(false));//取消反白

        // 换行
        stream.write(lineFeed());
    }

    /**
     * 设置反白模式（黑底白字）
     * @param enable true:启用 false:禁用
     */
    public static byte[] setReverseMode(boolean enable){
        return new byte[]{29, 66, enable ? (byte)1 : (byte)0}; // GS B
    }

    // 获取GBK编码下的字符串长度
    private static int getGbkLength(String str) {
        try {
            return str.getBytes("GBK").length;
        } catch (Exception e) {
            return str.length();
        }
    }

    //格式化时间
    @SuppressLint("SimpleDateFormat")
    public static String formatDate(Long date, String pattern){
        return new SimpleDateFormat(pattern).format(date);
    }

    /**
     * 格式化价格
     * 要求：
     *      1、存在小数位，四舍五入
     *      2、4位及以上加上千分号
     * @param numberStr
     * @return
     */
    public static String formatPrintPrice(String numberStr) {
        if (numberStr == null || numberStr.isEmpty()) {
            return "";
        }

        // 检查是否为有效数字格式
        if (!numberStr.matches("-?\\d+(\\.\\d+)?")) {
            return numberStr;
        }

        // 分离整数和小数部分
        String[] parts = numberStr.split("\\.");
        String integerPart = parts[0];
        boolean hasDecimal = parts.length > 1;

        // 四舍五入处理
        long value;
        if (hasDecimal) {
            // 获取小数部分第一位数字
            int firstDecimalDigit = Integer.parseInt(parts[1].substring(0, 1));
            value = Long.parseLong(integerPart);
            if (firstDecimalDigit >= 5) {
                value = integerPart.startsWith("-") ? value - 1 : value + 1;
            }
        } else {
            value = Long.parseLong(integerPart);
        }

        // 添加千分位（长度大于等于4）
        String absValueStr = String.valueOf(Math.abs(value));
        if (absValueStr.length() >= 4) {
            StringBuilder sb = new StringBuilder(String.valueOf(value));
            int startPos = value < 0 ? 1 : 0;
            for (int i = sb.length() - 3; i > startPos; i -= 3) {
                sb.insert(i, ",");
            }
            return sb.toString();
        }

        return String.valueOf(value);
    }

}
